﻿Public Class clControlBasico
    Public Enum Donde
        Arriba = 0
        Abajo
        Izquierda
        Derecha
        DiagonalArribaDerecha
        DiagonalAbajoDerecha
        DiagonalArribaIzquierda
        DiagonalAbajoIzquierda
        Ninguno
        Posicion 'Es lo mismo que quedarse quieto o estar encima/debajo de.
    End Enum
    Private _UltimaDireccion As Donde = Donde.Abajo
    ''' <summary>
    ''' Muestra la última dirección realizada.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property UltimaDireccion As Donde
        Get
            Return _UltimaDireccion
        End Get
    End Property

    ''' <summary>
    ''' Exclusiva para aquí. Solo tiene un parámetro extra.
    ''' </summary>
    ''' <remarks></remarks>
    Private Class Direcciones : Inherits Coordenadas
        Public Property Direccion As clControlBasico.Donde
        Public Sub New(ByVal X As Integer, ByVal y As Integer, ByVal donde As clControlBasico.Donde)
            MyBase.new(X, y)
            Direccion = donde
        End Sub
    End Class
   
    Private Shared MisCoordenadasDeMovimiento As New List(Of Direcciones) From {New Direcciones(0, 0, Donde.Posicion), New Direcciones(1, 0, Donde.Derecha), New Direcciones(-1, 0, Donde.Izquierda), New Direcciones(0, -1, Donde.Arriba), New Direcciones(0, 1, Donde.Abajo), New Direcciones(1, 1, Donde.DiagonalAbajoDerecha), New Direcciones(-1, 1, Donde.DiagonalAbajoIzquierda), New Direcciones(1, -1, Donde.DiagonalArribaDerecha), New Direcciones(-1, -1, Donde.DiagonalArribaIzquierda)} 'ME veo obligado a crearlo aquí...
    
    ''' <summary>
    ''' Busca casillas de un tipo en base a una casilla modelo alrededor de quien -casillas circundantes- Si si coincide la dirección del control basico con la posición del objeto lo retorna inmediatamente o también si está justo debajo/encima. si se encuentra excesivamente lejos regresará "ninguno"
    ''' </summary>
    ''' <param name="Quien">Quien tomamos como referencia para mirar a su alrededor</param>
    ''' <param name="que">Que casilla buscamos</param>
    ''' <param name="donde">En dónde la buscamos</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function BuscarQue(ByVal Quien As clControlBasico, ByVal que As clCasilla, ByVal donde As clMapa) As Donde
        Dim X As Integer = Quien.Control.Left / lado
        Dim Y As Integer = Quien.Control.Top / lado
        Dim respuesta As Donde = clControlBasico.Donde.Ninguno 'Regresará esto si pasa del próximo for sin suerte alguna.
        For Each z As Direcciones In MisCoordenadasDeMovimiento
            If posible((X + z.MiX), (Y + z.MiY), donde) AndAlso donde.CasillasMapa((X + z.MiX), (Y + z.MiY)).GetType = que.GetType Then
                respuesta = z.Direccion
                If respuesta = Quien.UltimaDireccion Or respuesta = clControlBasico.Donde.Posicion Then
                    Exit For
                End If
            End If
        Next
        Return respuesta
    End Function
    ''' <summary>
    ''' regresa true si la casilla que se busca está en la dirección a la que mira el control
    ''' </summary>
    ''' <param name="que">Modelo del tipo de casilla que buscamos</param>
    ''' <param name="donde">En qué mapa</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function EncontrarQue(ByVal que As clCasilla, ByVal donde As clMapa) As Boolean
        Return EncontrarQue(que, donde, False)
    End Function
    ''' <summary>
    ''' regresa true si la casilla que se busca está en la dirección a la que mira el control o si vale pisarlo y esta el control encima.
    ''' </summary>
    ''' <param name="que"> casilla que buscamos</param>
    ''' <param name="donde">En qué mapa</param>
    ''' <param name="ValePisarlo">¿Vale pisar la casilla?</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function EncontrarQue(ByVal Que As clCasilla, ByVal donde As clMapa, ByVal ValePisarlo As Boolean) As Boolean
        Dim X As Integer = Me.Control.Left / lado
        Dim Y As Integer = Me.Control.Top / lado
        For Each z As Direcciones In MisCoordenadasDeMovimiento
            If posible((X + z.MiX), (Y + z.MiY), donde) AndAlso donde.CasillasMapa((X + z.MiX), (Y + z.MiY)).Equals(Que) Then 'Si son del mismo tipo entonces pasa. los equals responden al tipo. 
                'TODO en caso de que no funcione correctamente la anterior versión hacía esta pregunta : "AndAlso donde.casillasMapa((X + z.MiX), (Y + z.MiY)).gettype=que.gettype" y funcionaba perfectamente.
                If z.Direccion = Me.UltimaDireccion OrElse (z.Direccion = clControlBasico.Donde.Posicion And ValePisarlo) Then
                    Return True ' Si coincide esto...
                End If
            End If
        Next
        Return False
    End Function
    
    ''' <summary>
    ''' Función qué regresa la posición del mapa de un objeto coordenadas. En el caso de que haya que pisarlo solo regresara una coordenada -de la clase coordenadas, en caso contrario regresará tantos pares como objetos encontrados
    ''' </summary>
    ''' <param name="Que">Modelo de la casilla que buscamos</param>
    ''' <param name="donde">Mapa donde lo buscamos</param>
    ''' <param name="HayQuePisarlo">¿Es necesario pisarlo?</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function EncontrarQueDonde(ByVal Que As clCasilla, ByVal donde As clMapa, ByVal HayQuePisarlo As Boolean) As List(Of Coordenadas)
        Dim respuesta As New List(Of Coordenadas)
        Dim X As Integer = Me.Control.Left / lado
        Dim Y As Integer = Me.Control.Top / lado
        For Each z As Direcciones In MisCoordenadasDeMovimiento
            If posible((X + z.MiX), (Y + z.MiY), donde) AndAlso donde.CasillasMapa((X + z.MiX), (Y + z.MiY)).GetType = Que.GetType Then
                If z.Direccion = clControlBasico.Donde.Posicion And HayQuePisarlo Then
                    respuesta.Add(New Coordenadas((X + z.MiX), (Y + z.MiY)))
                    Exit For
                Else
                    respuesta.Add(New Coordenadas((X + z.MiX), (Y + z.MiY)))
                End If

            End If
        Next
        Return respuesta
    End Function
    ''' <summary>
    ''' Functión que dice si existe una posición o no. Si la posición está a nothing la toma como si no estubiera.
    ''' </summary>
    ''' <param name="x">posicion x a mirar</param>
    ''' <param name="y">posición y a mirar</param>
    ''' <param name="donde">el mapa donde miramos.</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function posible(ByVal x As Integer, ByVal y As Integer, ByVal donde As clMapa) As Boolean
        Try
            Return Not donde.CasillasMapa(x, y).Control Is Nothing 'Tampoco sería util que un mapa tubiese casillas "Nothing".
        Catch ex As Exception
            Return False 'Si da error es falso seguro.
        End Try
    End Function
    Public Const lado As Integer = 48
    Protected _Control As Control = Nothing
    Public ReadOnly Property Control As Control
        Get
            Return _Control
        End Get
    End Property

    ''' <summary>
    ''' Cambia -o añade si no tiene- un control. -necesario para los movimientos-
    ''' </summary>
    ''' <param name="control">¿Qué control añadir?</param>
    ''' <remarks></remarks>
    Public Sub CambiarControl(ByVal control As Control)
        _Control = control
        _Control.Size = New Point(lado, lado)
    End Sub
    ''' <summary>
    ''' Se mueve el control en base a un mapa
    ''' </summary>
    ''' <param name="donde">Dirección a la que moverse</param>
    ''' <param name="mapa">Mapa que toma para saber si puede moverse</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Moverme(ByVal donde As Donde, ByVal mapa As clMapa) As String
        Dim x As Integer
        Dim y As Integer
        Dim NX As Integer = 0
        Dim NY As Integer = 0
        _UltimaDireccion = donde 'Aquí se marca la últiam dirección intentada.
        Try 'Comprueba un buen posicionamiento.
            x = _Control.Left / lado
            y = _Control.Top / lado
        Catch ex As Exception
            Return "Objeto mal posicionado"
        End Try


        Try
            Select Case donde
                Case clControlBasico.Donde.Abajo
                    NX = x
                    NY = y + 1
                    '_Control.Location = mapa.Mapa(x, y + 1).control.Location
                Case clControlBasico.Donde.Arriba
                    NX = x
                    NY = y - 1
                    '_Control.Location = mapa.Mapa(x, y - 1).control.Location
                Case clControlBasico.Donde.Derecha
                    NX = x + 1
                    NY = y
                    '_Control.Location = mapa.Mapa(x + 1, y).control.Location
                Case clControlBasico.Donde.Izquierda
                    NX = x - 1
                    NY = y
                    '_Control.Location = mapa.Mapa(x - 1, y).control.Location
                Case clControlBasico.Donde.DiagonalAbajoDerecha
                    NX = x + 1
                    NY = y + 1
                    '_Control.Location = mapa.Mapa(x + 1, y + 1).control.Location
                Case clControlBasico.Donde.DiagonalAbajoIzquierda
                    NX = x - 1
                    NY = y + 1
                    '_Control.Location = mapa.Mapa(x - 1, y + 1).control.Location
                Case clControlBasico.Donde.DiagonalArribaDerecha
                    NX = x + 1
                    NY = y - 1
                    '_Control.Location = mapa.Mapa(x + 1, y - 1).control.Location
                Case clControlBasico.Donde.DiagonalArribaIzquierda
                    NX = x - 1
                    NY = y - 1
                    '_Control.Location = mapa.Mapa(x - 1, y - 1).control.Location
            End Select
            If mapa.ValidarAccesoAEn(NX, NY, Me) Then
                _Control.Location = mapa.CasillasMapa(NX, NY).Control.Location
            Else
                Return "Pared"
            End If
        Catch ex As Exception

            _Control.Location = mapa.CasillasMapa(x, y).Control.Location
            Return "Pared. " & ex.Message
        End Try
        Return "Todo en orden"
    End Function

    ''' <summary>
    ''' Coloca el control directamente en la posición especificada. Si puede
    ''' </summary>
    ''' <param name="NuevaSituacionX">Situación X</param>
    ''' <param name="NuevaSituacionY"> Situación Y</param>
    ''' <param name="mapa"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Teletransportar(ByVal NuevaSituacionX As Integer, ByVal NuevaSituacionY As Integer, ByVal mapa As clMapa) As String
        If Not mapa.ValidarAccesoAEn(NuevaSituacionX, NuevaSituacionY, Me) Then Return "No puede ir ahí"
        _Control.Location = mapa.CasillasMapa(NuevaSituacionX, NuevaSituacionY).Control.Location
        Return "Todo en orden"
    End Function
End Class
''' <summary>
''' Mini clase diseñada para almacenar coordenadas.
''' </summary>
''' <remarks></remarks>
Public Class Coordenadas
    Public Property MiX As Integer
    Public Property MiY As Integer
    Public Sub New(ByVal X As Integer, ByVal y As Integer)
        MiX = X
        MiY = y
    End Sub
End Class

